package net.guerlab.mall.seller.print.websocket;

import java.net.URI;
import java.util.Properties;

import javax.websocket.ContainerProvider;
import javax.websocket.WebSocketContainer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.guerlab.mall.seller.print.callback.Callback;

public class SellerClient extends Thread {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(SellerClient.class);

    private static URI serviceHost;

    private static URI testServiceHost;

    private SellerClientWebSocket clientWebSocket = new SellerClientWebSocket();

    private Callback connectionFinalCallback;

    private boolean connectioned;

    private long nextSendTime;

    private String username;

    private String password;

    private boolean isTest;

    static {
        Properties config = new Properties();
        try {
            config.load(SellerClient.class.getResourceAsStream("/config/config.properties"));
        } catch (Exception e) {
            LOGGER.debug(e.getMessage(), e);
        }

        serviceHost = URI.create(config.getProperty("serviceUrl", "ws://service.71xiaoxin.com/websocket/seller.do"));
        testServiceHost = URI.create(config.getProperty("testServiceUrl", "ws://test.service.71xiaoxin.com/websocket/seller.do"));
    }

    public final void setUsername(String username) {
        this.username = username;
    }

    public final void setPassword(String password) {
        this.password = password;
    }

    public final void setTest(boolean isTest) {
        this.isTest = isTest;
    }

    public final boolean isConnectioned() {
        return connectioned;
    }

    public void registerLoginCallback(BusinessInterface callback) {
        if (callback == null) {
            return;
        }
        clientWebSocket.registerBusinessModel("loginSuccess:", callback);
    }

    public void registerLoginErrorCallback(BusinessInterface callback) {
        if (callback == null) {
            return;
        }
        clientWebSocket.registerBusinessModel("loginError:", callback);
    }

    public void registerConnectionFinalCallback(Callback callback) {
        if (callback == null) {
            return;
        }

        connectionFinalCallback = callback;
    }

    @Override
    public void run() {
        initRegisterBusinessModel();
        connectionService();
        initHeartbeat();
    }

    public void login() {
        if (clientWebSocket.isOpen()) {
            clientWebSocket.sendMessage("login:" + username + "&" + password);
        }

        username = null;
        password = null;
    }

    public void close() {
        if (clientWebSocket != null) {
            clientWebSocket.close();
        }
    }

    private void initRegisterBusinessModel() {
        clientWebSocket.registerBusinessModel("printOrder:", new OrderPrintBusiness());
        clientWebSocket.registerBusinessModel("printOfflineOrder:", new OfflinePrintBusiness());
    }

    private void connectionService() {
        WebSocketContainer container = ContainerProvider.getWebSocketContainer();

        try {
            
            URI url = isTest ? testServiceHost : serviceHost;
            
            LOGGER.info("usr uri : {}", url);
            
            container.connectToServer(clientWebSocket, url);
            connectioned = true;
        } catch (Exception e) {
            if (connectionFinalCallback != null) {
                connectionFinalCallback.callback(new Object[0]);
            }
            
            LOGGER.info("connection final : {}", e.getMessage());
        }
    }

    private void initHeartbeat() {

        Runnable run = new Runnable() {

            public void run() {
                while (true) {
                    if (System.currentTimeMillis() <= nextSendTime || !clientWebSocket.isOpen()) {
                        continue;
                    }

                    nextSendTime = System.currentTimeMillis() + 30 * 1000;

                    clientWebSocket.sendMessage("heartbeat");
                }
            }
        };

        new Thread(run).start();
    }
}
